using System;
using RayDen.Library.Core.Primitives;
using RayDen.Library.Data.Imaging;

namespace RayDen.Library.Components.Surface.Spectral
{
    [Serializable]
    public class MetalMaterial : SpectralBrdf
    {
        public override BrdfType Type
        {
            get { return BrdfType.Glossy; }
        }

        public MetalMaterial(RgbSpectrum refl, float exp, bool reflSpecularBounce)
        {
            Kr = ColorFactory.CreateRegularSpd(ref refl, SpectrumType.Reflectance);
            exponent = 1f / (exp + 1f);
            reflectionSpecularBounce = reflSpecularBounce;
        }

        public override bool IsDiffuse() { return false; }
        public override bool IsSpecular() { return true; }

        private SpectralDistribution Kr;
        public float exponent;
        public bool reflectionSpecularBounce;
     
        public bool IsSpecularBounce { get { return reflectionSpecularBounce; } }

        public override void F(ref Vector wo, ref Vector wi, ref Normal N, float lambda, out float fs)
        {
            throw new NotImplementedException();
        }

        public override void Sample_f(ref Vector wo, ref Normal geoNormal, ref Normal shadeN, float lambda, ref SurfaceTextureData surfaceData, float u0, float u1, float u2, out BsdfSampleData result)
        {
            exponent = 1f / (surfaceData.Exponent + 1f);
            result = new BsdfSampleData();
            result.Wi = SurfaceBsdf.GlossyReflection(ref wo, exponent, ref shadeN, u0, u1);
            if (Vector.Dot(ref result.Wi, ref shadeN) > 0f)
            {
                result.Type = reflectionSpecularBounce ? BrdfType.Specular : BrdfType.Diffuse;
                result.Pdf = 1f;
                result.Lambda = Kr.Sample(lambda);
                result.F = surfaceData.Specular;
            }
            else
            {
                result.F = new RgbSpectrum(0f);
                result.Pdf = 0f;
                result.Type = BrdfType.Diffuse;
            }
        }
    };
}